package com.example.curvedemo.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.os.Handler;
import android.os.Looper;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.core.content.res.ResourcesCompat;
import androidx.core.widget.NestedScrollView;
import androidx.viewpager.widget.ViewPager;

import com.example.curvedemo.R;
import com.example.curvedemo.util.CanvasUtils;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * 新版曲线图
 */
public class CurveNewView extends View {
    /**
     * 上下文
     */
    private Context mContext = null;
    /**
     * 用于处理滑动冲突
     */
    private NestedScrollView scrollView;
    private ViewPager viewPager;
    /**
     * 画图区域的宽高
     */
    private float width, height;
    /**
     * 纵坐标平均每一行的高度
     */
    private float fRowHeight;
    /**
     * 横坐标平均每一列的宽带
     */
    private float fColWidth = 0;
    /**
     * 横纵向字体大小单位sp
     */
    private int txtSize = 12;
    /**
     * 纵坐标、横坐标的字体画笔
     */
    private TextPaint textPaint = null;
    /**
     * 横坐标画笔
     */
    private Paint horizontalPaint = null;
    /**
     * 固定的虚线画笔
     */
    private Paint dottedLinePaint = null;
    /**
     * 绘制选中的竖线
     */
    private Paint checkLinePaint = null;
    /**
     * 画Y轴的刻度线
     */
    private Paint yLinePaint = null;
    /**
     * 画空心圆
     */
    private Paint circlePaint = null;
    /**
     * 选中背景画笔
     */
    private Paint checkPaint = null;
    /**
     * 选中日期画笔
     */
    private Paint datePaint = null;
    /**
     * 选中数据画笔
     */
    private TextPaint checkValuePaint = null;
    /**
     * 选中颜色1提示画笔（小圆点）
     */
    private Paint checkOneTipPaint = null;

    /**
     * 选中提示颜色圆的半径 单位像素
     */
    private int checkcircleRadius = 4;
    /**
     * 圆的半径 单位dp
     */
    private int circleRadius = 3;
    private float circle_width = 1.2f;
    /**
     * 折线画笔
     */
    private Paint linePaint = null;

    private Paint innerPaint = null;
    /**
     * 阴影画笔
     */
    private Paint shadowPaint = null;

    /**
     * 控件左间距（用于计算点击位置）
     */
    private int left_spacing = 0;
    /**
     * 选中框文案最大宽度
     */
    private int max_txt_width = 0;

    /**
     * 左边展示刻度对应的线（默认第一条线（-1代表柱状图））
     */
    private int leftScaleNum = 0;

    /**
     * 是否需要绘制下标
     */
    private boolean isBomTip = true;
    //折线的弯曲率
    private float smoothness = 0.35f;

    private String hollowColor = "#ffffff";

    /**
     * 线颜色
     */
    private String[] lineColors = new String[]{"#52C41A", "#FFAD0D", "#307DFF", "#7C48EE", "#23D4EC", "#F03D3D", "#FF7A25", "#A66262"};

    private float[] weights = new float[]{1.15f, 1.75f, 2.4f, 3.1f, 3.9f, 4.5f};
    /**
     * 线阴影颜色
     */
    private String shadowColor = "#0F52C41A";

    /**
     * 横行字体宽带
     */
    private float horizontalTextWidth = 0;

    private int ynum = 5;

    /**
     * 横向起始位置
     */
    private float xStart = 0;
    /**
     * 右边绘制游标的宽度
     */
    private float xEnd = 0;
    private float[] xPoint;
    /**
     * 选中的item -999为未选中
     */
    private int check_item = -999;

    /**
     * 放开时选中的item -999为未选中
     */
    private int release_check_item = -999;

    /**
     * 是否绘制左边坐标刻度
     */
    private boolean isLeftTip = true;

    /**
     * 是否绘制阴影
     */
    private boolean isShadow = true;

    /**
     * 是否绘制y轴刻度线
     */
    private boolean isScaleLine = true;

    /**
     * x轴数据
     */
    private List<CurveNewData.XData> xDataList = new ArrayList<>();
    /**
     * 线数据
     */
    private List<CurveNewData.LineData> lineDataList = new ArrayList<>();

    /**
     * 柱状图数据
     */
    private List<CurveNewData.LineData> columnarDataList = new ArrayList<>();

    /**
     * 顶部提示数据
     */
    private List<CurveNewData.LineData> lineTopDataList = new ArrayList<>();

    private List<float[]> Points = new ArrayList<>();

    private float[] yColumnarPoint;

    private List<Path> paths = new ArrayList<>();

    private Path shadowPath;

    private int minColumnarWidth = 0;
    private int maxColumnarWidth = 0;
    /**
     * 柱状图画笔
     */
    private Paint columnarPaint = null;
    /**
     * 柱状图
     */
    private Path columnarPath = new Path();

    private Handler mainHandler = new Handler(Looper.getMainLooper());

    /**
     * 选中提示框
     */
    private RectF checkRectF;

    private ItemOclickListener itemOclickListener;

    private ReleaseOclickListener releaseOclickListener;

    public ItemOclickListener getItemOclickListener() {
        return itemOclickListener;
    }

    /**
     * 设置手指松开监听
     *
     * @param releaseOclickListener
     */
    public void setReleaseOclickListener(ReleaseOclickListener releaseOclickListener) {
        this.releaseOclickListener = releaseOclickListener;
    }

    /**
     * 设置点击监听
     *
     * @param itemOclickListener
     */
    public void setItemOclickListener(ItemOclickListener itemOclickListener) {
        this.itemOclickListener = itemOclickListener;
    }

    /**
     * 设置点击监听
     *
     * @param itemOclickListener
     */
    public void setItemOclickListener(ItemOclickListener itemOclickListener, NestedScrollView scrollView) {
        this.itemOclickListener = itemOclickListener;
        this.scrollView = scrollView;
    }

    /**
     * 设置点击监听
     *
     * @param itemOclickListener
     */
    public void setItemOclickListener(ItemOclickListener itemOclickListener, ViewPager viewPager) {
        this.itemOclickListener = itemOclickListener;
        this.viewPager = viewPager;
    }

    /**
     * 设置点击监听
     *
     * @param itemOclickListener
     */
    public void setItemOclickListener(ItemOclickListener itemOclickListener, NestedScrollView scrollView, ViewPager viewPager) {
        this.itemOclickListener = itemOclickListener;
        this.scrollView = scrollView;
        this.viewPager = viewPager;
    }

    /**
     * 设置控件左间距（用于计算点击位置）
     *
     * @param left_spacing
     */
    public void setLeft_spacing(int left_spacing) {
        this.left_spacing = left_spacing;
    }

    /**
     * 设置左边刻度数据对应的线（-1代表柱状图）
     *
     * @param leftScaleNum 对应的线
     */
    public void setLeftScaleNum(int leftScaleNum) {
        this.leftScaleNum = leftScaleNum;
    }

    /**
     * 设置字体大小
     *
     * @param context
     * @param txtSize
     */
    public void setTxtSize(Context context, int txtSize) {
        this.txtSize = txtSize;
        initWillUsed(context);
    }

    /**
     * 设置是否需要绘制下标
     *
     * @param bomTip
     */
    public void setBomTip(boolean bomTip) {
        isBomTip = bomTip;
        invalidate();
    }

    public void setScrollView(NestedScrollView scrollView) {
        this.scrollView = scrollView;
    }

    public void setViewPager(ViewPager viewPager) {
        this.viewPager = viewPager;
    }

    public CurveNewView(Context context) {
        super(context);
        initWillUsed(context);
    }

    public CurveNewView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initWillUsed(context);
    }

    /**
     * 初始化将使用到的参数
     */
    private void initWillUsed(Context context) {
        mContext = context;
        max_txt_width = dip2px(mContext, 180);
        textPaint = new TextPaint();
        Typeface face = ResourcesCompat.getFont(mContext, R.font.barlow_semibold);
        textPaint.setColor(Color.parseColor("#666666"));
        textPaint.setAntiAlias(true);
//        textPaint.setTypeface(Typeface.create("sans-serif-light", Typeface.BOLD));
        textPaint.setTypeface(face);
        textPaint.setTextSize(sp2px(context, txtSize));
        horizontalPaint = new Paint();
        horizontalPaint.setColor(Color.parseColor("#C8C8C8"));
        horizontalPaint.setAntiAlias(true);
        horizontalPaint.setStrokeWidth(1);
        checkLinePaint = new Paint();
        checkLinePaint.setStrokeWidth(3);
        checkLinePaint.setAntiAlias(true);
        checkLinePaint.setColor(Color.parseColor("#52C41A"));
        yLinePaint = new Paint();
        yLinePaint.setStrokeWidth(dip2px(mContext, 1));
        yLinePaint.setColor(Color.parseColor("#eeeeee"));
        yLinePaint.setAntiAlias(true);
        yLinePaint.setStyle(Paint.Style.STROKE);
        dottedLinePaint = new Paint();
        dottedLinePaint.setStyle(Paint.Style.STROKE);
        dottedLinePaint.setColor(Color.parseColor("#eeeeee"));
        dottedLinePaint.setAntiAlias(true);
        circlePaint = new Paint();
        circlePaint.setStyle(Paint.Style.FILL);
        circlePaint.setAntiAlias(true);

        linePaint = new Paint();
        linePaint.setStrokeWidth(dip2px(mContext, 2));
        linePaint.setAntiAlias(true);
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeJoin(Paint.Join.ROUND);
        linePaint.setStrokeCap(Paint.Cap.ROUND);

        innerPaint = new Paint();
        innerPaint.setColor(Color.WHITE);
        innerPaint.setStyle(Paint.Style.FILL);
        innerPaint.setAntiAlias(true);

        checkPaint = new Paint();
        checkPaint.setColor(Color.parseColor("#e6000000"));
        checkPaint.setAntiAlias(true);
        datePaint = new Paint();
        datePaint.setColor(Color.parseColor("#FFFFFF"));
        datePaint.setAntiAlias(true);
        datePaint.setTypeface(Typeface.create("sans-serif-light", Typeface.BOLD));
//        datePaint.setTypeface(face);
        datePaint.setTextSize(sp2px(context, 10));

        checkValuePaint = new TextPaint();
        checkValuePaint.setColor(Color.parseColor("#FFFFFF"));
        checkValuePaint.setAntiAlias(true);
//        checkValuePaint.setTypeface(Typeface.create("sans-serif-light", Typeface.BOLD));
        checkValuePaint.setTypeface(face);
        checkValuePaint.setTextSize(sp2px(context, 11));

        checkOneTipPaint = new Paint();
        checkOneTipPaint.setAntiAlias(true);

        shadowPaint = new Paint();
        shadowPaint.setAntiAlias(true);
        shadowPaint.setStrokeJoin(Paint.Join.ROUND);
        shadowPaint.setColor(Color.parseColor(shadowColor));

        columnarPaint = new Paint();
        columnarPaint.setAntiAlias(true);
        columnarPath = new Path();

        //默认算选中圆半径
        xEnd = dip2px(mContext, circleRadius);
        minColumnarWidth = dip2px(mContext, 1);
        maxColumnarWidth = dip2px(mContext, 8);
    }

    /**
     * 是否绘制Y轴刻度线
     *
     * @param scaleLine
     */
    public void setScaleLine(boolean scaleLine) {
        isScaleLine = scaleLine;
    }

    /**
     * 设置数据（柱状图且带顶部提示数据）
     *
     * @param xDataList
     * @param lineDataList
     * @param lineDataList
     * @param lineTopDataList
     * @param numY
     */
    public void setData(List<CurveNewData.XData> xDataList, List<CurveNewData.LineData> lineDataList, List<CurveNewData.LineData> columnarDataList, List<CurveNewData.LineData> lineTopDataList, int numY) {
        this.lineTopDataList = lineTopDataList;
        this.xDataList = xDataList;
        this.lineDataList = lineDataList;
        this.columnarDataList = columnarDataList;
        ynum = numY;
        width = getWidth();
        height = getHeight();
        if (isBomTip) {
            int lines = 1;
            for (int i = 0; i < xDataList.size(); i++) {
                String horizontalContent = xDataList.get(i).getTitle();
                String[] strings = horizontalContent.split("\n");
                lines = strings.length;
            }
            fRowHeight = (float) (height - dip2px(mContext, 24) - sp2px(mContext, txtSize) * lines) / ynum;
        } else {
            fRowHeight = (float) (height - sp2px(mContext, txtSize)) / ynum;
        }
        xStart = 0;
        xEnd = dip2px(mContext, circleRadius);
        fColWidth = 0;
        check_item = -999;
        if (isShadow) {
            linePaint.setStrokeWidth(dip2px(mContext, 2));
        } else {
            linePaint.setStrokeWidth(dip2px(mContext, 1.5f));
        }
        xPoint = new float[xDataList.size() + 1];
        setWillNotDraw(false);
        new Thread() {
            @Override
            public void run() {
                super.run();
                setVerticalAnnualValueY();
                getLeftMaxWidth();
                setVerticalInfo();
                setZBData();
                setLineData();
            }
        }.start();
    }

    /**
     * 设置数据
     *
     * @param xDataList    x轴数据
     * @param lineDataList 线数据
     * @param numY
     */
    public void setData(List<CurveNewData.XData> xDataList, List<CurveNewData.LineData> lineDataList, int numY) {
        setData(xDataList, lineDataList, null, null, numY);
    }

    /**
     * 设置数据（带顶部提示数据）
     *
     * @param xDataList    x轴数据
     * @param lineDataList 线数据
     * @param numY
     */
    public void setData(List<CurveNewData.XData> xDataList, List<CurveNewData.LineData> lineDataList, List<CurveNewData.LineData> lineTopDataList, int numY) {
        setData(xDataList, lineDataList, null, lineTopDataList, numY);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (!isEmpty(lineDataList)) {
            drawVertical(canvas);
            drawHorizontal(canvas);
            drawYLine(canvas);
            drawColumnar(canvas);
            drawLine(canvas);
            drawCheck(canvas);
        }
    }

    /**
     * 设置线对应的每格高度值
     */
    public void setVerticalAnnualValueY() {
        long verticalAnnualValueY;
        for (int i = 0; i < lineDataList.size(); i++) {
            verticalAnnualValueY = (long) Math.ceil(getMaxValue(i) / (float) ynum);
            if (verticalAnnualValueY == 0) {
                verticalAnnualValueY = 1;
            }
            lineDataList.get(i).setVerticalAnnualValueY(verticalAnnualValueY);
            long minValue = getLineMinValue(lineDataList.get(i).getData());
            double bs = 0;
            lineDataList.get(i).setZero_num((int) bs);
            lineDataList.get(i).setVerticalValueY_min(minValue);
        }
        //设置柱状图
        if (!isEmpty(columnarDataList)) {
            for (int i = 0; i < columnarDataList.size(); i++) {
                verticalAnnualValueY = (long) Math.ceil(getColumnarMaxValue(i) / (float) ynum);
                if (verticalAnnualValueY == 0) {
                    verticalAnnualValueY = 1;
                }
                columnarDataList.get(i).setVerticalAnnualValueY(verticalAnnualValueY);
                long minValue = getLineMinValue(columnarDataList.get(i).getData());
                double bs = 0;
                columnarDataList.get(i).setZero_num((int) bs);
                columnarDataList.get(i).setVerticalValueY_min(minValue);
            }
        }
    }

    /**
     * 获取线的最小值
     *
     * @param data
     * @return
     */
    public long getLineMinValue(List<CurveNewData.LineData.ItemData> data) {
        long minValue = 0;
        if (data != null && !data.isEmpty()) {
            for (CurveNewData.LineData.ItemData bean : data) {
                if (minValue > bean.getValue()) {
                    minValue = bean.getValue();
                }
            }
        }
        return minValue;
    }

    /**
     * 获取最大间距值
     *
     * @param i
     * @return
     */
    public long getMaxValue(int i) {
        long maxValue = 0;
        long max = 0, min = 0;
        boolean isFirst = true;
        for (CurveNewData.LineData.ItemData bean : lineDataList.get(i).getData()) {
            if (isFirst) {
                max = bean.getValue();
                min = bean.getValue();
                isFirst = false;
            } else {
                if (max < bean.getValue()) {
                    max = bean.getValue();
                }
                if (min > bean.getValue()) {
                    min = bean.getValue();
                }
            }
        }
        //大于0的话设置最小值为0
        if (min > 0) {
            min = 0;
        }
        maxValue = Math.abs(max) + Math.abs(min);
        maxValue = (long) Math.ceil(maxValue * getWeight(i));
        return maxValue;
    }

    /**
     * 获取最大间距值
     *
     * @param i
     * @return
     */
    public long getColumnarMaxValue(int i) {
        long maxValue = 0;
        long max = 0, min = 0;
        boolean isFirst = true;
        for (CurveNewData.LineData.ItemData bean : columnarDataList.get(i).getData()) {
            if (isFirst) {
                max = bean.getValue();
                min = bean.getValue();
                isFirst = false;
            } else {
                if (max < bean.getValue()) {
                    max = bean.getValue();
                }
                if (min > bean.getValue()) {
                    min = bean.getValue();
                }
            }
        }
        //大于0的话设置最小值为0
        if (min > 0) {
            min = 0;
        }
        maxValue = Math.abs(max) + Math.abs(min);
        maxValue = (long) Math.ceil(maxValue * getWeight(-1));
        return maxValue;
    }

    /**
     * 获取权重
     *
     * @param i
     * @return
     */
    public float getWeight(int i) {
        float weight;
        if (!isEmpty(columnarDataList)) {
            i = i + 1;
        }
        if (i < weights.length) {
            weight = weights[i];
        } else {
            weight = 1;
        }
        return weight;
    }

    /**
     * 计算左边刻度值绘制最大宽度
     */
    private void getLeftMaxWidth() {
        if (isLeftTip) {
            if (isEmpty(columnarDataList)) {
                for (int i = 0; i <= ynum; i++) {
                    boolean isPercentage = lineDataList.get(0).isPercentage();
                    String content;
                    long value = lineDataList.get(0).getVerticalValueY_min() + (lineDataList.get(0).getVerticalAnnualValueY() * (ynum - i));
                    if (isPercentage) {
                        content = value + "%";
                    } else {
                        content = conversion(value / lineDataList.get(0).getMultiple());
                    }
                    if (xStart < textPaint.measureText(content)) {
                        xStart = textPaint.measureText(content);
                    }
                }
            } else {
                for (int i = 0; i <= ynum; i++) {
                    boolean isPercentage = columnarDataList.get(0).isPercentage();
                    String content;
                    long value = columnarDataList.get(0).getVerticalValueY_min() + (columnarDataList.get(0).getVerticalAnnualValueY() * (ynum - i));
                    if (isPercentage) {
                        content = value + "%";
                    } else {
                        content = conversion(value / columnarDataList.get(0).getMultiple());
                    }
                    if (xStart < textPaint.measureText(content)) {
                        xStart = textPaint.measureText(content);
                    }
                }
            }
            //图表和刻度默认间距10dp
            xStart = xStart + dip2px(mContext, 10);
        } else {
            xStart = 0;
        }
        xEnd = dip2px(mContext, circleRadius);
    }

    /**
     * 设置横向需要计算的数据，需在getLeftMaxWidth()方法后调用
     */
    private void setVerticalInfo() {
        for (int i = 0; i < xDataList.size(); i++) {
            String horizontalContent = xDataList.get(i).getTitleStr();
            float t_w = textPaint.measureText(horizontalContent);
            if (t_w > horizontalTextWidth) {
                horizontalTextWidth = t_w;
            }
            float c_w = (width - xEnd - xStart) / xDataList.size();
            if (c_w > fColWidth) {
                fColWidth = c_w;
            }
            if (isBomTip) {
                //只有一个数据特殊处理放在中间
                if (xDataList.size() == 1) {
                    fColWidth = width / 2;
                }
            }
        }
    }

    /**
     * 设置线数据到path中
     */
    private void setLineData() {
        //最后绘制折线防止被阴影遮盖
        paths.clear();
        for (int i = 0; i < lineDataList.size(); i++) {
            if (xPoint.length > 0 && i < Points.size() && Points.get(i).length > 0) {
                Path linePath = new Path();
                linePath.moveTo(xPoint[0], Points.get(i)[0]);
                if (showShadow(i)) {
                    shadowPath = new Path();
                    shadowPath.moveTo(xPoint[0], Points.get(i)[0]);
                }
                for (int j = 0; j < lineDataList.get(i).getData().size() - 1; j++) {
                    if ((j + 1) < xPoint.length) {
                        linePath.lineTo(xPoint[j], Points.get(i)[j]);
                        float x1 = xPoint[j] + (xPoint[j + 1] - xPoint[j]) * smoothness;
                        float y1 = Points.get(i)[j];
                        float x2 = xPoint[j] + (xPoint[j + 1] - xPoint[j]) * (1 - smoothness);
                        float y2 = Points.get(i)[j + 1];
                        linePath.cubicTo(x1, y1, x2, y2, xPoint[j + 1], Points.get(i)[j + 1]);
                        if (showShadow(i)) {
                            shadowPath.lineTo(xPoint[j], Points.get(i)[j]);
                            shadowPath.cubicTo(x1, y1, x2, y2, xPoint[j + 1], Points.get(i)[j + 1]);
                        }
                    }
                }
                if (showShadow(i)) {
                    if (!lineDataList.get(i).getData().isEmpty()) {
                        shadowPath.lineTo(xPoint[lineDataList.get(i).getData().size() - 1], ynum * fRowHeight + sp2px(mContext, txtSize) / 2);
                    } else {
                        shadowPath.lineTo(xPoint[0], ynum * fRowHeight + sp2px(mContext, txtSize) / 2);
                    }
                    shadowPath.lineTo(xPoint[0], ynum * fRowHeight + sp2px(mContext, txtSize) / 2);
                    shadowPath.close();
                }
                paths.add(linePath);
            }
        }
        if (mainHandler == null) {
            invalidate();
        } else {
            mainHandler.post(() -> {
                // 在主线程更新 UI
                invalidate();
            });
        }
    }

    /**
     * 是否绘制阴影
     *
     * @param i 线
     * @return 是否可以绘制阴影
     */
    private boolean showShadow(int i) {
        boolean showShadow = false;
        if (isShadow && i == 0 && isEmpty(columnarDataList)) {
            showShadow = true;
        } else {
            showShadow = false;
        }
        return showShadow;
    }

    /**
     * 画纵向数据
     */
    private void drawVertical(Canvas canvas) {
        if (isLeftTip) {
            CurveNewData.LineData lineData = null;
            switch (leftScaleNum) {
                case -1:
                    if (!isEmpty(columnarDataList)) {
                        lineData = columnarDataList.get(0);
                    }
                    break;
                default:
                    if (leftScaleNum < lineDataList.size()) {
                        lineData = lineDataList.get(leftScaleNum);
                    }
                    break;
            }
            if (lineData != null) {
                for (int i = 0; i <= ynum; i++) {
                    boolean isPercentage = lineData.isPercentage();
                    String content;
                    long value = lineData.getVerticalValueY_min() + (lineData.getVerticalAnnualValueY() * (ynum - i));
                    if (isPercentage) {
                        content = keep2(value / (float) lineData.getMultiple()) + "%";
                    } else {
                        content = conversion(value / (float) lineData.getMultiple());
                    }
                    canvas.drawText(content, 0, i * fRowHeight + sp2px(mContext, txtSize), textPaint);
                }
            }
        }
    }

    /**
     * 画横向数据
     */
    private void drawHorizontal(Canvas canvas) {
        //横向刻度过大时每个刻度里面有的数据量
        int v = 1;
        if (xDataList.size() > 7) {
            v = (int) Math.ceil(xDataList.size() / (double) 7);
        }
        if (isBomTip) {
            for (int i = 0; i < xDataList.size(); i++) {
                String horizontalContent = xDataList.get(i).getTitle();
                String[] strings = horizontalContent.split("\n");
                int lines = strings.length;
                String maxStr = "";
                for (String s : strings) {
                    if (maxStr.length() < s.length()) {
                        maxStr = s;
                    }
                }
                horizontalTextWidth = textPaint.measureText(maxStr);
                if (i == 0 || i % v == 0) {
                    CanvasUtils.drawText(canvas, textPaint, xPoint[i] - horizontalTextWidth / 2, ynum * fRowHeight + sp2px(mContext, txtSize)
                            + dip2px(mContext, 4), dip2px(mContext, 60), lines, horizontalContent);
//                    canvas.drawText(horizontalContent, xPoint[i] - horizontalTextWidth / 2, ynum * fRowHeight + sp2px(mContext, txtSize)
//                            + dip2px(mContext, 10), textPaint);
                    //绘制x坐标轴刻度
                    canvas.drawLine(xPoint[i], ynum * fRowHeight + sp2px(mContext, txtSize) / 2, xPoint[i],
                            ynum * fRowHeight + sp2px(mContext, txtSize) / 2 + dip2px(mContext, 5), horizontalPaint);
                }
            }
        }
    }

    /**
     * 画Y轴的刻度线
     */
    private void drawYLine(Canvas canvas) {
        if (isScaleLine) {
            for (int i = 0; i <= ynum; i++) {
                if (i == ynum) {
                    yLinePaint.setPathEffect(new DashPathEffect(new float[]{0, 0}, 0));
                    canvas.drawLine(xStart, i * fRowHeight + sp2px(mContext, txtSize) / 2, width - xEnd,
                            i * fRowHeight + sp2px(mContext, txtSize) / 2, yLinePaint);
                } else {
                    yLinePaint.setPathEffect(new DashPathEffect(new float[]{12, 12}, 0));
                    //绘制长度为4的实线后再绘制长度为4的空白区域，0位间隔
                    canvas.drawLine(xStart, i * fRowHeight + sp2px(mContext, txtSize) / 2, width - xEnd,
                            i * fRowHeight + sp2px(mContext, txtSize) / 2, yLinePaint);
                }
            }
        }
    }

    /**
     * 绘制选中的效果
     */
    private void drawCheck(Canvas canvas) {
        if (xDataList != null && xDataList.size() == 1) {
            check_item = 0;
        }
        if (check_item >= 0 && check_item < xDataList.size()) {
            //绘制选中线
            canvas.drawLine(xPoint[check_item], sp2px(mContext, txtSize) / 2, xPoint[check_item], ynum * fRowHeight + sp2px(mContext, txtSize) / 2, checkLinePaint);
            for (int i = 0; i < lineDataList.size(); i++) {
                if (i < Points.size() && check_item < Points.get(i).length) {
                    circlePaint.setColor(Color.parseColor(getLineColor(i)));
                    canvas.drawCircle(xPoint[check_item], Points.get(i)[check_item], dip2px(mContext, circleRadius), circlePaint);
                    circlePaint.setColor(Color.parseColor(hollowColor));
                    canvas.drawCircle(xPoint[check_item], Points.get(i)[check_item], dip2px(mContext, circleRadius - circle_width), circlePaint);
                }
            }
            String xStr;
            if (TextUtils.isEmpty(xDataList.get(check_item).getTitleStr())) {
                xStr = xDataList.get(check_item).getTitle();
            } else {
                xStr = xDataList.get(check_item).getTitleStr();
            }
            float check_width, check_height = sp2px(mContext, 10) + dip2px(mContext, 24);
            float max_w = 0f;
            float date_width = datePaint.measureText(xStr);
            if (max_w < date_width) {
                max_w = date_width;
            }
            String content;
            if (lineTopDataList != null && !lineTopDataList.isEmpty()) {
                for (CurveNewData.LineData bean : lineTopDataList) {
                    content = getContentStr(bean.getTitle(), bean.getData().get(check_item), bean);
                    if (max_w < checkValuePaint.measureText(content)) {
                        max_w = checkValuePaint.measureText(content);
                    }
                    check_height += (sp2px(mContext, 11) + dip2px(mContext, 8));
                }
            }
            if (!isEmpty(columnarDataList)) {
                for (CurveNewData.LineData bean : columnarDataList) {
                    content = getContentStr(bean.getTitle(), bean.getData().get(check_item), bean);
                    if (max_w < checkValuePaint.measureText(content)) {
                        max_w = checkValuePaint.measureText(content);
                    }
                    check_height += (sp2px(mContext, 11) + dip2px(mContext, 8));
                }
            }
            for (CurveNewData.LineData bean : lineDataList) {
                if (bean.getData() != null && !bean.getData().isEmpty()) {
                    content = getContentStr(bean.getTitle(), bean.getData().get(check_item), bean);
                    if (max_w < checkValuePaint.measureText(content)) {
                        max_w = checkValuePaint.measureText(content);
                    }
                    check_height += (sp2px(mContext, 11) + dip2px(mContext, 8));
                }
            }
            //判断是否大于最大预设文案长度
            if (max_w > max_txt_width) {
                max_w = max_txt_width;
            }
            check_width = max_w + dip2px(mContext, 36);
            int t = 0, b = 0, l = 0, r = 0;
            if (xPoint[check_item] > check_width + 40) {
                l = (int) (xPoint[check_item] - check_width - 40);
                r = (int) (xPoint[check_item] - 40);
            } else {
                l = (int) (xPoint[check_item] + 40);
                r = (int) (xPoint[check_item] + check_width + 40);
            }
            t = 0;
            b = (int) (t + check_height);
            if (t < 0) {
                t = 0;
                b = (int) (t + check_height);
            }
            checkRectF = new RectF(l, t, r, b);
            //绘制圆角矩形
            canvas.drawRoundRect(checkRectF, dip2px(mContext, 6), dip2px(mContext, 6), checkPaint);
            int d_x = l + dip2px(mContext, 12);
            int d_y = t + dip2px(mContext, 20);
            canvas.drawText(xStr, d_x, d_y, datePaint);
            if (!isEmpty(lineTopDataList)) {
                for (int i = 0; i < lineTopDataList.size(); i++) {
                    String contentStr = getContentStr(lineTopDataList.get(i).getTitle(), lineTopDataList.get(i).getData().get(check_item), lineTopDataList.get(i));
                    if (i > 0) {
                        d_y = d_y + sp2px(mContext, 11) + dip2px(mContext, 8);
                    } else {
                        d_y = d_y + dip2px(mContext, 8);
                    }
                    CanvasUtils.drawText(canvas, checkValuePaint, d_x, d_y, (int) max_w, 1, contentStr);
                }
                d_y = d_y + dip2px(mContext, 10);
            }
            if (!isEmpty(columnarDataList)) {
                CurveNewData.LineData columnarData = columnarDataList.get(0);
                if (columnarData.getData() != null && !columnarData.getData().isEmpty()) {
                    String contentStr = getContentStr(columnarData.getTitle(), columnarData.getData().get(check_item), columnarData);
                    d_y = d_y + dip2px(mContext, 8);
                    //由于获取颜色判断有柱状图会自动加一所以设置为-1（也就是默认取下标为0的颜色）
                    circlePaint.setColor(Color.parseColor(getLineColor(-1)));
                    //下面坐标属于微调不是实际计算
                    canvas.drawCircle(d_x + dip2px(mContext, 4), d_y + dip2px(mContext, 9), dip2px(mContext, checkcircleRadius), circlePaint);
                    CanvasUtils.drawText(canvas, checkValuePaint, d_x + dip2px(mContext, 12), d_y, (int) max_w, 1, contentStr);
                    d_y = d_y + dip2px(mContext, 10);
                }
            }
            for (int i = 0; i < lineDataList.size(); i++) {
                if (lineDataList.get(i).getData() != null && !lineDataList.get(i).getData().isEmpty()) {
                    String contentStr = getContentStr(lineDataList.get(i).getTitle(), lineDataList.get(i).getData().get(check_item), lineDataList.get(i));
                    if (i > 0) {
                        d_y = d_y + sp2px(mContext, 11) + dip2px(mContext, 8);
                    } else {
                        d_y = d_y + dip2px(mContext, 8);
                    }
                    circlePaint.setColor(Color.parseColor(getLineColor(i)));
                    //下面坐标属于微调不是实际计算
                    canvas.drawCircle(d_x + dip2px(mContext, 4), d_y + dip2px(mContext, 9), dip2px(mContext, checkcircleRadius), circlePaint);
                    CanvasUtils.drawText(canvas, checkValuePaint, d_x + dip2px(mContext, 12), d_y, (int) max_w, 1, contentStr);
                }
            }
        }
    }

    /**
     * 获取值得展示数据
     *
     * @return 展示的值
     */
    public String getContentStr(String titleStr, CurveNewData.LineData.ItemData itemData, CurveNewData.LineData bean) {
        String contentStr;
        String valueStr;
        if (TextUtils.isEmpty(itemData.getValueStr())) {
            if (bean.isPercentage()) {
                valueStr = keep2(itemData.getValue() / (float) bean.getMultiple()) + "%";
            } else {
                valueStr = conversion2(itemData.getValue() / (float) bean.getMultiple());
            }
        } else {
            valueStr = itemData.getValueStr();
        }
        if (TextUtils.isEmpty(itemData.getDataTip())) {
            contentStr = titleStr + "：" + valueStr;
        } else {
            contentStr = titleStr + "：" + valueStr + itemData.getDataTip();
        }
        return contentStr;
    }

    /**
     * 单位换算（保留一位小数向上或向下取整）
     *
     * @param num 需要转换的数值
     * @return 转换后的字符串
     */
    public String conversion(float num) {
        return formatNumber(num, 1, true);
    }

    /**
     * 单位换算(保留2位小数四舍五入)
     *
     * @param num 需要转换的数值
     * @return 转换后的字符串
     */
    public String conversion2(float num) {
        return formatNumber(num, 2, false);
    }

    /**
     * 格式化数字
     *
     * @param num           需要转换的数值
     * @param decimalPlaces 保留小数位数
     * @param isCeiling     是否向上取整(true为向上取整，false为四舍五入)
     * @return 格式化后的字符串
     */
    private String formatNumber(float num, int decimalPlaces, boolean isCeiling) {
        if (num == 0) {
            return "0";
        }

        // 确定单位和换算比例
        float scale;
        String unit = "";

        if (Math.abs(num) < 10000) {
            scale = 1f;
        } else if (Math.abs(num) < 100000000) {
            scale = 10000f;
            unit = "w";
        } else {
            scale = 100000000f;
            unit = "亿";
        }

        // 计算转换后的值
        float value = num / scale;

        // 根据小数位数和取整方式处理
        if (isCeiling) {
            // 保留一位小数向上或向下取整
            value = num < 0 ? (float) Math.floor(value * 10) / 10 : (float) Math.ceil(value * 10) / 10;
        } else {
            // 保留两位小数四舍五入
            value = (float) Math.round(value * 100) / 100;
        }

        return keep2(value) + unit;
    }

    /**
     * 设置是否展示左边刻度
     *
     * @param leftTip
     */
    public void setLeftTip(boolean leftTip) {
        isLeftTip = leftTip;
        invalidate();
    }

    /**
     * 设置坐标数据
     * 计算折线图和柱状图的坐标点位置
     */
    public void setZBData() {
        // 计算X轴坐标点
        calculateXAxisPoints();

        // 计算折线图Y轴坐标点
        calculateLineYAxisPoints();

        // 计算柱状图Y轴坐标点
        calculateColumnarYAxisPoints();
    }

    /**
     * 计算X轴坐标点位置
     */
    private void calculateXAxisPoints() {
        for (int i = 0; i < xDataList.size(); i++) {
            // 只有一个数据时特殊处理，放在中间
            if (xDataList.size() == 1) {
                xPoint[i] = width / 2;
            } else {
                xPoint[i] = xStart + fColWidth / 2 + i * fColWidth;
            }
        }
    }

    /**
     * 计算折线图Y轴坐标点位置
     */
    private void calculateLineYAxisPoints() {
        Points.clear();
        for (int i = 0; i < lineDataList.size(); i++) {
            CurveNewData.LineData data = lineDataList.get(i);
            float[] point = new float[data.getData().size()];

            for (int j = 0; j < data.getData().size(); j++) {
                point[j] = calculateYPoint(data, j);
            }
            Points.add(point);
        }
    }

    /**
     * 计算柱状图Y轴坐标点位置
     */
    private void calculateColumnarYAxisPoints() {
        if (isEmpty(columnarDataList)) {
            return;
        }

        // 柱状图默认只有一条所以固定取第一个下标
        CurveNewData.LineData data = columnarDataList.get(0);
        yColumnarPoint = new float[data.getData().size()];

        for (int j = 0; j < data.getData().size(); j++) {
            yColumnarPoint[j] = calculateYPoint(data, j);
        }
    }

    /**
     * 计算单个Y轴坐标点
     *
     * @param data  数据对象
     * @param index 数据索引
     * @return Y轴坐标值
     */
    private float calculateYPoint(CurveNewData.LineData data, int index) {
        float baseY = sp2px(mContext, txtSize) / 2 + fRowHeight * ynum;
        float scale = fRowHeight / Math.abs(data.getVerticalAnnualValueY());
        long value = data.getData().get(index).getValue();

        if (data.getVerticalValueY_min() >= 0) {
            return value == 0 ? baseY : baseY - scale * Math.abs(value);
        } else {
            return baseY - scale * (value - data.getVerticalValueY_min());
        }
    }

    /**
     * 画折线 和 阴影
     */
    private void drawLine(Canvas canvas) {
        if (isShadow && shadowPath != null) {
            canvas.drawPath(shadowPath, shadowPaint);
        }
        for (int i = 0; i < lineDataList.size(); i++) {
            try {
                if (showShadow(i)) {
                    linePaint.setStrokeWidth(dip2px(mContext, 2f));
                } else {
                    linePaint.setStrokeWidth(dip2px(mContext, 1.5f));
                }
                linePaint.setColor(Color.parseColor(getLineColor(i)));
                if (paths != null && i < paths.size()) {
                    canvas.drawPath(paths.get(i), linePaint);
                }
            } catch (Exception e) {
            }
        }
    }

    /**
     * 绘制柱状图
     *
     * @param canvas
     */
    public void drawColumnar(Canvas canvas) {
        if (!isEmpty(columnarDataList)) {
            //柱状图默认只有一条所以固定取第一个下标
            CurveNewData.LineData data = columnarDataList.get(0);
            if (data == null || isEmpty(data.getData())) {
                return;
            }
            int l = (int) (fColWidth / 4);
            if (l < minColumnarWidth) {
                l = minColumnarWidth;
            }
            if (l > maxColumnarWidth) {
                l = maxColumnarWidth;
            }
            int jx = (int) (ynum * fRowHeight + sp2px(mContext, txtSize) / 2);
            for (int i = 0; i < xDataList.size(); i++) {
                if (i < data.getData().size() && xPoint != null && i < xPoint.length && yColumnarPoint != null && i < yColumnarPoint.length) {
                    columnarPath.reset();
                    columnarPath.moveTo(xPoint[i] - l, yColumnarPoint[i]);
                    columnarPath.lineTo(xPoint[i] + l, yColumnarPoint[i]);
                    columnarPath.lineTo(xPoint[i] + l, jx);
                    columnarPath.lineTo(xPoint[i] - l, jx);
                    Shader lShader = new LinearGradient(0, jx, 0, yColumnarPoint[i],
                            Color.parseColor("#8052C41A"), Color.parseColor("#808AE438"), Shader.TileMode.REPEAT);
                    columnarPaint.setShader(lShader);
                    try {
                        canvas.drawPath(columnarPath, columnarPaint);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            if (check_item >= 0 && check_item < data.getData().size()) {
                //绘制选中柱状图
                columnarPath.reset();
                columnarPath.moveTo(xPoint[check_item] - l, yColumnarPoint[check_item]);
                columnarPath.lineTo(xPoint[check_item] + l, yColumnarPoint[check_item]);
                columnarPath.lineTo(xPoint[check_item] + l, jx);
                columnarPath.lineTo(xPoint[check_item] - l, jx);
                Shader lShader = new LinearGradient(0, jx, 0, yColumnarPoint[check_item],
                        Color.parseColor("#52C41A"), Color.parseColor("#8AE438"), Shader.TileMode.REPEAT);
                columnarPaint.setShader(lShader);
                try {
                    canvas.drawPath(columnarPath, columnarPaint);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 获取线颜色
     *
     * @param i
     * @return
     */
    public String getLineColor(int i) {
        String lineColor;
        if (!isEmpty(columnarDataList)) {
            i = i + 1;
        }
        //数据超出预设颜色就设置透明看不见
        if (i < lineColors.length) {
            lineColor = lineColors[i];
        } else {
            lineColor = "#00000000";
        }
        return lineColor;
    }

    public int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    public static int sp2px(Context var0, float var1) {
        float var2 = var0.getResources().getDisplayMetrics().scaledDensity;
        return (int) (var1 * var2 + 0.5F);
    }

    private Handler handler = new Handler();
    /**
     * 是否移到
     */
    private boolean isMove = false;
    private float x = 0, y = 0;
    private float tb = 0, lr = 0;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (check_item != -999) {
                    if (checkRectF != null && checkRectF.contains(event.getX(), event.getY())) {
                        check_item = -999;
                        invalidate();
                        return false;
                    }
                }
                x = (int) event.getX();
                y = (int) event.getY();
                tb = 0;
                lr = 0;
                if (itemOclickListener != null) {
                    click(event.getX());
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (itemOclickListener != null) {
                    click(event.getX());
                    if (scrollView != null) {
                        lr = lr + Math.abs(x - event.getX());
                        tb = tb + Math.abs(y - event.getY());
                        //计算为记录当前坐标用于下次计算滑动距离
                        x = event.getX();
                        y = event.getY();
                        //左右权重添加20%
                        if (lr * 1.2 > tb) {
                            //不允许ScrollView截断点击事件，点击事件由子View处理
                            scrollView.requestDisallowInterceptTouchEvent(true);
                        } else {
                            releaseCtrl();
                            //允许ScrollView截断点击事件，ScrollView可滑动
                            scrollView.requestDisallowInterceptTouchEvent(false);
                        }
                    }
                    if (viewPager != null) {
                        //不允许viewPager截断点击事件，点击事件由子View处理
                        viewPager.requestDisallowInterceptTouchEvent(true);
                    } else {
                        //允许
//                        viewPager.requestDisallowInterceptTouchEvent(true);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                releaseCtrl();
                if (handler != null) {
                    handler.removeCallbacksAndMessages(null);
                }
                break;
        }
        //返回true表示不消耗此事件，事件继续传递，返回flase表示事件消耗
        return true;
    }

    /**
     * 释放操作
     */
    private void releaseCtrl() {
        if (releaseOclickListener != null) {
            if (release_check_item != check_item) {
                release_check_item = check_item;
                releaseOclickListener.onClick(release_check_item);
            }
        }
    }

    /**
     * * 判断是否有长按动作发生 * @param lastX 按下时X坐标 * @param lastY 按下时Y坐标 *
     *
     * @param thisX 移动时X坐标 *
     * @param thisY 移动时Y坐标 *
     */
    static boolean isLongPressed(float lastX, float lastY, float thisX, float thisY) {
        float offsetX = Math.abs(thisX - lastX);
        float offsetY = Math.abs(thisY - lastY);
        if (offsetX <= 10 && offsetY <= 10) {
            return true;
        } else {
            return false;
        }
    }

    public void click(float x) {
        for (int i = 0; i < xDataList.size(); i++) {
            //点击判断位置需要手动加每个刻度的一半，这样每次点击都有选中效果，体验较好
            if (x >= xPoint[i] + left_spacing - fColWidth / 2 && x <= xPoint[i] + left_spacing + fColWidth / 2) {
                check_item = i;
                itemOclickListener.onClick(i);
                invalidate();
                return;
            }
        }
    }

    public interface ItemOclickListener {
        void onClick(int p);
    }

    public interface ReleaseOclickListener {
        void onClick(int p);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mainHandler != null) {
            mainHandler.removeCallbacksAndMessages(null); // 清除所有消息和回调
            mainHandler = null; // 置空引用（可选）
        }
    }

    /**
     * 列表是否为空
     *
     * @param list 列表
     * @return 是否为空
     */
    public static boolean isEmpty(List list) {
        if (list == null || list.isEmpty()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 最大保存2位小数点
     *
     * @param s
     * @return
     */
    public static String keep2(double s) {
        DecimalFormat decimalFormat = new DecimalFormat("#.##");//构造方法的字符格式这里如果小数不足2位,会以0补足.
        String distanceString = decimalFormat.format(s);//format 返回的是字符串
        return distanceString;
    }

}
